#include <iostream>
using namespace std;

struct A { virtual ~A() {} }; // 有虚函数的类可用“运行时类型鉴别（RTTI）”
struct B { virtual ~B() {} };
struct C : public A, public B {}; // 多继承，麻烦之源

void test(const string& info, B* pb){ // 编译时无法确定pb所指对象的实际类型
  cout << info << pb << ' ' << dynamic_cast<C*>(pb) << endl;
}

int main() {
  B b;
  C c;
  A *pa = &c;
  B *pb = &c;
  cout << "&c: " << &c << endl;
  // pa实际指向C类对象，可以向下转成C*。
  cout << "pa: " << pa << " C*: " << dynamic_cast<C*>(pa) << endl;
  // A、B毫无关联，一般不能转换（结果为空指针）
  // 但pa所指对象的RTTI是C类，含有B类对象，可以从A*转成B*
  cout << "pa: " << pa << " B*: " << dynamic_cast<B*>(pa) << endl;
  // 拿到一个基类指针不知道是指向基类对象、还是派生类对象。
  // 要到运行时（runtime）才能确定。
#if 0
  int x; cin >> x;
  test("RT: ", x ? &b : &c); // 比如由用户在运行时选择实参，编译时无法确定实参类型：
  // 甚至编译test()时有可能派生类还没写出来（分别编译、动态链接）
#endif
  test("pb: ", pb); // 向下转型成功
  test("&b: ", &b); // 向下转型失败，但毕竟检测到了错误。
  cout << "&b: " << &b << ' ' << static_cast     <C*>(&b) << endl; // b不是C类对象，转换结果错误。
  cout << "&b: " << &b << ' ' << reinterpret_cast<C*>(&b) << endl; // 强制解读也是错误。
}
